package xyz.imeans.w.service;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import xyz.imeans.w.annotion.Table;
import xyz.imeans.w.config.CreateDataConfig;
import xyz.imeans.w.config.CreateEnum;
import xyz.imeans.w.config.InitCreateFactory;
import xyz.imeans.w.config.ObjCreateFactory;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class MysqlService implements CreateService, InitializingBean {

    private final CreateDataConfig createDataConfig;
    public MysqlService (CreateDataConfig createDataConfig) {
        this.createDataConfig = createDataConfig;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        InitCreateFactory.initCreateService(CreateEnum.Mysql, this);
    }

    @Override
    public void exec(CreateDataConfig.Config config) {
        int count = config.getCount();
        if(count <= 0) {
            return;
        }
        Connection conn = null;
        Statement stmt = null;
        ResultSet resultSet = null;
        try {
            Map<String, String> map = createDataConfig.getSource().get("mysql");
            Class.forName(map.get("driver-class-name"));
            conn = DriverManager.getConnection(map.get("url"), map.get("username"), map.get("password"));
            stmt = conn.createStatement();

            Class<?> aClass = Class.forName(config.getModel());
            Table table = aClass.getAnnotation(Table.class);

            // 检查是否存在表
             resultSet = stmt.executeQuery("SELECT COUNT(*) cnt FROM information_schema.tables " +
                    "WHERE table_name = '" + table.value() + "';");
             int cnt = 0;
             if(resultSet.next()) {
                 cnt = resultSet.getInt(1);
             }

            // 获取表字段
            Map<String, String> columns = ObjCreateFactory.getFieldColumn(aClass);
            if(columns.size() == 0) {
                return;
            }

            // 创建表
            if(cnt == 0) {
                StringBuilder sb = new StringBuilder("CREATE TABLE ");
                sb.append("`").append(table.value()).append("`").append("(\n");
                String idColumn = columns.remove("my_system_data_id");
                int ii = columns.size() - 1;
                for (Map.Entry<String, String> entry : columns.entrySet()) {
                    sb.append("`").append(entry.getValue()).append("`");
                    if(entry.getValue().equals(idColumn)) {
                        sb.append(" VARCHAR(255) NOT NULL ");
                    } else {
                        sb.append(" VARCHAR(255) NULL DEFAULT NULL ");
                    }
                    if (ii > 0) {
                        sb.append(",");
                    } else {
                        sb.append(",\n PRIMARY KEY (`").append(idColumn).append("`) USING BTREE ");
                    }
                    sb.append("\n");
                    ii--;
                }
                sb.append(")\n").append("COLLATE='utf8_general_ci'\n").append("ENGINE=InnoDB;");
                System.out.println(sb);
                stmt.execute(sb.toString());
            }

            // 生成数据
            List<Map<String, Object>> list = new ArrayList<>(count);
            for (int i = 0; i < count; i++) {
                Map<String, Object> d = ObjCreateFactory.createObj(aClass);
                if(d.size() > 0) {
                    list.add(d);
                }
            }
            if(list.size() == 0) {
                return;
            }

            // 拼接查询语句,2000条数据一批次
            StringBuilder sb = new StringBuilder("insert into ").append(table.value()).append(" (");
            columns.remove("my_system_data_id");
            int ii = columns.size() - 1;
            for (Map.Entry<String, String> entry : columns.entrySet()) {
                sb.append("`").append(entry.getValue()).append("`");
                if(ii > 0) {
                    sb.append(",");
                }
                ii--;
            }
            sb.append(")").append(" values ");

            int num = list.size() / 2000 + (list.size() % 2000 > 0 ? 1 : 0);
            for (int c = 1; c <= num; c++) {
                List<Map<String, Object>> l = list.subList((c - 1) * 2000, Math.min(c * 2000, list.size()));

                StringBuilder sbb = new StringBuilder(sb);
                StringBuilder sb1 = new StringBuilder();
                for (int i = 0; i < l.size(); i++) {
                    Map<String, Object> d = l.get(i);
                    sb1.append(" (");
                    int j = columns.size() - 1;
                    for (String k : columns.keySet()) {
                        sb1.append("'").append(d.get(k)).append("'");
                        if(j > 0) {
                            sb1.append(",");
                        }
                        j--;
                    }
                    sb1.append(")");
                    if(i < l.size() - 1) {
                        sb1.append(",");
                    }
                }
                sbb.append(sb1).append(";");

                // 执行语句
                System.out.println(sbb);
                stmt.execute(sbb.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
